﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Windows.Forms;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using RetrieveEntityDetails.CrmDiscoveryServiceProxy;
using RetrieveEntityDetails.BusinessLogic;
using RetrieveEntityDetails.Utility;
using System.Net;
using Microsoft.Crm.SdkTypeProxy.Metadata;
using Microsoft.Crm.Sdk.Metadata;
using System.Threading;


namespace RetrieveEntityDetails
{
    public partial class frmRetrieveEntityDetails : Form
    {
        CRMDiscoveryServiceHelper oCRMDiscoveryServiceHelper;
        MetaDataServiceHelper oMetaDataServiceHelper;
        DataTableManager Table;
        string FolderPath = string.Empty;
        CrmMetadata[] CRMMetadata;
        string PassportTicket;
        string[] OrgFriendlyNames;
        public static bool IsAtleastOneEntitySelected = false;

        public frmRetrieveEntityDetails()
        {
            InitializeComponent();
        }

        #region Event Methods

        void frmRetrieveEntityDetails_Load(object sender, EventArgs e)
        {
            RestoreAppState();
            if (rbtnWindowsAuthentication.Checked)
            {
                txtDomain.Enabled = false;
                txtPassword.Enabled = false;
                txtUsername.Enabled = false;
                btnExportCSV.Enabled = false;
            }
            cbOrganization.Enabled = false;
            btnExportCSV.Enabled = false;
            btnConnect.Enabled = false;
        }

        private void frmRetrieveEntityDetails_FormClosed(object sender, FormClosedEventArgs e)
        {
            SaveAppState();
        }

        void cmdRetrieveOrganization_Click(object sender, EventArgs e)
        {
            try
            {
                cbOrganization.SelectedIndex = -1;
                cbOrganization.Items.Clear();
                tvEntityList.Nodes.Clear();
                gboxEntityList.Enabled = chkboxSelectAll.Checked = false;

                string ErrorMessage = string.Empty;
                oCRMDiscoveryServiceHelper = new CRMDiscoveryServiceHelper();

                if (string.IsNullOrEmpty(txtServerName.Text))
                    ErrorMessage = "Please provide Server name";
                else if (string.IsNullOrEmpty(txtPortNumber.Text))
                    ErrorMessage = "Please provide port number";

                if (rbtnCustomAuthentication.Checked)
                {
                    if (txtUsername.Text == null || txtUsername.Text == string.Empty)
                        ErrorMessage = "Please provide Username";
                    else if (txtPassword.Text == null || txtPassword.Text == string.Empty)
                        ErrorMessage = "Please provide Password";
                    else if (txtDomain.Text == null || txtDomain.Text == string.Empty && !chkboxCRMOnline.Checked)
                        ErrorMessage = "Please provide Domain name";
                }

                if (!string.IsNullOrEmpty(ErrorMessage))
                {
                    MessageBox.Show(ErrorMessage);
                }
                else
                {
                    RetrieveOrganization();
                    cbOrganization.Enabled = btnConnect.Enabled = true;
                }
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerText);
                cbOrganization.Enabled = btnConnect.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                cbOrganization.Enabled = btnConnect.Enabled = false;
            }
            toolStripStatusLabel.Text = string.Empty;
        }

        void rbtnCustomAuthentication_Click(object sender, EventArgs e)
        {
            try
            {
                if (!rbtnWindowsAuthentication.Checked)
                {
                    txtDomain.Enabled = true;
                    txtPassword.Enabled = true;
                    txtUsername.Enabled = true;
                }
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerText);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void rbtnWindowsAuthentication_Click(object sender, EventArgs e)
        {
            try
            {
                if (rbtnWindowsAuthentication.Checked)
                {
                    txtDomain.Enabled = false;
                    txtPassword.Enabled = false;
                    txtUsername.Enabled = false;
                }
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerText);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                if (cbOrganization.SelectedIndex == -1)
                {
                    MessageBox.Show("Please select an organization");
                }
                else
                {
                    SetMetaDataServiceHelperClassAttributes();
                    CRMMetadata = oMetaDataServiceHelper.GetEntityList();
                    tvEntityList.Nodes.Clear();
                    tvEntityList.Sort();
                    ParseMetadata();
                    gboxEntityList.Enabled = true;
                    btnExportCSV.Enabled = true;
                }
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerText);
                gboxEntityList.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                gboxEntityList.Enabled = false;
            }
        }

        void btnExportCSV_Click(object sender, EventArgs e)
        {
            try
            {
                bool IsAtleastOneEntitySelected = false;
                foreach (TreeNode oNode in tvEntityList.Nodes)
                {
                    if (oNode.Checked)
                        IsAtleastOneEntitySelected = true;
                }
                if (!IsAtleastOneEntitySelected)
                    MessageBox.Show("Please select atleast one entity to export.");
                else
                {
                    dlgFolder.ShowDialog();
                    string FolderPath = dlgFolder.SelectedPath;
                    if (!string.IsNullOrEmpty(FolderPath))
                        foreach (TreeNode oNode in tvEntityList.Nodes)
                        {
                            if (oNode.Checked)
                            {
                                GenerateCode(FolderPath, oNode);
                                IsAtleastOneEntitySelected = true;
                            }
                        }
                }
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerText);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void chkboxHttps_CheckedChanged(object sender, EventArgs e)
        {
            txtPortNumber.Enabled = !chkboxHttps.Checked;
            txtPortNumber.Text = chkboxHttps.Checked ? "443" : "80";
        }

        void chkboxCRMOnline_CheckedChanged(object sender, EventArgs e)
        {
            txtPortNumber.Enabled = txtDomain.Enabled = txtServerName.Enabled = !chkboxCRMOnline.Checked;
            chkboxHttps.Checked = chkboxCRMOnline.Checked;
            txtPortNumber.Text = chkboxHttps.Checked ? "443" : "80";
            txtServerName.Text = chkboxHttps.Checked ? "dev.crm.dynamics.com" : string.Empty;
        }

        #endregion

        #region Internal Methods

        private void SaveAppState()
        {
            ApplicationStateDO appState = new ApplicationStateDO();
            appState.domain = txtDomain.Text;
            appState.port = txtPortNumber.Text;
            appState.serverName = txtServerName.Text;
            appState.userName = txtUsername.Text;
            appState.isCRMOnline = chkboxCRMOnline.Checked;
            appState.isHTTPS = chkboxHttps.Checked;
            appState.isIFD = chkboxIFD.Checked;
            appState.isCustomAuthentication = rbtnCustomAuthentication.Checked;
            ApplicationStateManager.WriteApplicationState(appState);
        }

        private void RestoreAppState()
        {
            ApplicationStateDO appState = ApplicationStateManager.ReadApplicationState();
            if (appState == null) return;
            txtDomain.Text = appState.domain;
            txtPortNumber.Text = appState.port;
            txtServerName.Text = appState.serverName;
            txtUsername.Text = appState.userName;
            chkboxCRMOnline.Checked = appState.isCRMOnline;
            chkboxHttps.Checked = appState.isHTTPS;
            chkboxIFD.Checked = appState.isIFD;
            rbtnCustomAuthentication.Checked = appState.isCustomAuthentication;
            rbtnWindowsAuthentication.Checked = !rbtnCustomAuthentication.Checked;
        }

        void RetrieveOrganization()
        {
            oCRMDiscoveryServiceHelper.Username = txtUsername.Text;
            oCRMDiscoveryServiceHelper.Password = txtPassword.Text;
            oCRMDiscoveryServiceHelper.Domain = txtDomain.Text;
            oCRMDiscoveryServiceHelper.IsHTTPS = chkboxHttps.Checked;
            oCRMDiscoveryServiceHelper.IsIFD = chkboxIFD.Checked;
            oCRMDiscoveryServiceHelper.IsCRMOnline = chkboxCRMOnline.Checked;
            oCRMDiscoveryServiceHelper.PortNumber = txtPortNumber.Text;
            oCRMDiscoveryServiceHelper.ServerName = txtServerName.Text;
            string FriendlyNameCSV = string.Empty;
            foreach (OrganizationDetail OrgItem in oCRMDiscoveryServiceHelper.GetOrganizationList(out PassportTicket))
            {
                cbOrganization.Items.Add(OrgItem.OrganizationName);
                FriendlyNameCSV += OrgItem.FriendlyName + ",";
            }
            OrgFriendlyNames = FriendlyNameCSV.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        }

        void SetMetaDataServiceHelperClassAttributes()
        {
            oMetaDataServiceHelper = new MetaDataServiceHelper();
            oMetaDataServiceHelper.Username = txtUsername.Text;
            oMetaDataServiceHelper.Password = txtPassword.Text;
            oMetaDataServiceHelper.Domain = txtDomain.Text;
            oMetaDataServiceHelper.PortNumber = txtPortNumber.Text;
            oMetaDataServiceHelper.PassportTicket = PassportTicket;
            oMetaDataServiceHelper.IsHTTPS = chkboxHttps.Checked;
            oMetaDataServiceHelper.IsIFD = chkboxIFD.Checked;
            oMetaDataServiceHelper.IsCRMOnline = chkboxCRMOnline.Checked;
            oMetaDataServiceHelper.OrganizationName = cbOrganization.SelectedItem.ToString();
            oMetaDataServiceHelper.ServerName = chkboxCRMOnline.Checked ? OrgFriendlyNames[cbOrganization.SelectedIndex] + ".crm.dynamics.com" : txtServerName.Text;
        }

        void GenerateCode(string FolderPath, TreeNode oNode)
        {
            DataRow[] EntityRows = Table.FetchCheckedEntityAttributes((Guid)oNode.Tag);
            CSVFileWriter Writer = new CSVFileWriter();
            Writer.EntityName = oNode.Text;
            Writer.FolderPath = FolderPath;
            DataRow[] PickListRows = Table.FetchPickList((Guid)oNode.Tag);
            DataRow[] StateCodeRows = Table.FetchStateCode((Guid)oNode.Tag);
            DataRow[] StatusCodeRows = Table.FetchStatusCode((Guid)oNode.Tag);
            DataRow[] LookUpRows = Table.FetchLookupTypes((Guid)oNode.Tag);
            Writer.Write(EntityRows, PickListRows, LookUpRows, StateCodeRows, StatusCodeRows);
        }

        void ParseMetadata()
        {
            Table = new DataTableManager();
            foreach (Microsoft.Crm.Sdk.Metadata.EntityMetadata EntityItem in CRMMetadata)
            {
                if (!EntityItem.IsCustomizable.Value) continue;
                string EntityDisplayName = GetEnglishLocaleDisplayName(EntityItem.DisplayName.LocLabels);
                TreeNode EntityNode = tvEntityList.Nodes.Add(EntityDisplayName);
                EntityNode.Tag = EntityItem.MetadataId.Value;

                foreach (AttributeMetadata AttributeItem in EntityItem.Attributes)
                {

                    string AttributeDisplayName = GetEnglishLocaleDisplayName(AttributeItem.DisplayName.LocLabels);
                    if (AttributeDisplayName == string.Empty) continue;
                    Table.AttributeID = AttributeItem.MetadataId.Value;
                    Table.AttributeSchemaName = AttributeItem.LogicalName;
                    Table.EntitySchemaName = EntityItem.LogicalName;
                    Table.AttributeType = AttributeItem.AttributeType.Value.ToString();
                    Table.EntityID = EntityItem.MetadataId.Value;
                    Table.AttributeName = AttributeDisplayName;
                    Table.EntityName = EntityNode.Text;
                    Table.InsertEntityRow();
                    Table.InsertAttributeRow();
                    if (AttributeItem.AttributeType.Value == AttributeType.Picklist)
                    {
                        foreach (Option PickListOption in ((PicklistAttributeMetadata)AttributeItem).Options)
                        {
                            Table.PickListOptionDisplayName = GetEnglishLocaleDisplayName(PickListOption.Label.LocLabels);
                            Table.PickListOptionValue = PickListOption.Value.Value;
                            Table.InsertPickListRow();
                        }
                    }
                    if (AttributeItem.AttributeType.Value == AttributeType.Status)
                    {
                        foreach (Option Status in ((StatusAttributeMetadata)AttributeItem).Options)
                        {
                            Table.AttributeID = AttributeItem.MetadataId.Value;
                            Table.StatusCodeDisplayName = GetEnglishLocaleDisplayName(Status.Label.LocLabels);
                            Table.StatusCodeValue = Status.Value.Value;
                            Table.InsertStatusCodeRow();
                        }
                    }
                    if (AttributeItem.AttributeType.Value == AttributeType.State)
                    {
                        foreach (Option State in ((StateAttributeMetadata)AttributeItem).Options)
                        {
                            Table.AttributeID = AttributeItem.MetadataId.Value;
                            Table.StateCodeDisplayName = GetEnglishLocaleDisplayName(State.Label.LocLabels);
                            Table.StateCodeValue = State.Value.Value;
                            Table.InsertStateCodeRow();
                        }
                    }
                    if (AttributeItem.AttributeType.Value == AttributeType.Lookup && ((LookupAttributeMetadata)AttributeItem).Targets.Count > 0)
                    {
                        Table.LookupType = ((LookupAttributeMetadata)AttributeItem).Targets[0].ToString();
                        Table.InsertLookupTypeRow();
                    }
                }
            }
        }

        string GetEnglishLocaleDisplayName(LocLabel[] LocLabelItems)
        {
            foreach (LocLabel LocLabelItem in LocLabelItems)
            {
                if (LocLabelItem.LanguageCode.Value == 1033)
                {
                    return LocLabelItem.Label;
                }
            }
            return string.Empty;
        }

        void cbOrganization_EnabledChange(object sender, EventArgs e)
        {
            btnConnect.Enabled = cbOrganization.Enabled;
        }

        void chkSelectALL_CheckedChanged(object sender, EventArgs e)
        {
            bool Switch = chkboxSelectAll.Checked;
            foreach (TreeNode Entity in tvEntityList.Nodes)
            {
                Entity.Checked = Switch;
            }
        }

        void SetMetadataServiceHelperProperties(MetaDataServiceHelper oMetaDataServiceHelper)
        {
            oMetaDataServiceHelper.Username = txtUsername.Text;
            oMetaDataServiceHelper.Password = txtPassword.Text;
            oMetaDataServiceHelper.Domain = txtDomain.Text;
            oMetaDataServiceHelper.PortNumber = txtPortNumber.Text;
            oMetaDataServiceHelper.ServerName = txtServerName.Text;
            oMetaDataServiceHelper.OrganizationName = cbOrganization.SelectedItem.ToString();
        }

        #endregion

    }
}
